/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014-06-13
 * V4.0
 */
package com.jphenix.webserver.instancea;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.TreeSet;
import java.util.Vector;

import com.jphenix.servlet.filter.BaseFilter;
import com.jphenix.share.util.StringUtil;
import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.standard.servlet.api.ICookie;
import com.jphenix.standard.servlet.api.IHttpSession;
import com.jphenix.standard.servlet.api.IRequestDispatcher;
import com.jphenix.standard.servlet.api.IResponse;
import com.jphenix.standard.servlet.api.ServletInputStream;
import com.jphenix.standard.servlet.api.ServletOutputStream;
import com.jphenix.webserver.api.CookieImpl;
import com.jphenix.webserver.api.RequestImpl;
import com.jphenix.webserver.api.ResponseImpl;
import com.jphenix.webserver.api.ServletInputStreamImpl;
import com.jphenix.webserver.api.ServletOutputStreamImpl;
import com.jphenix.webserver.api.SessionImpl;

/**
 * 用户连接 (包含 Request Response)
 * com.jphenix.webserver.instancea.ServeConnection
 * 
 * 2019-04-16 修改了获取Content-Type值中，缺少后半部分的错误
 * 2019-04-18 修改了获取编码值错误
 * 2019-08-13 修改了报文头为标准格式（原来都是小写的）
 * 2019-08-17 修改了小写的host报文头主键导致的错误
 * 2019-09-17 整理了代码格式
 * 2019-09-20 去掉了调试打印堆栈信息
 * 2019-12-10 修改了获取报文头值报错
 * 2021-03-17 适配tomcat9中的 servlet-api.jar
 * 2022-09-04 重构了内置Servlet容器，不依赖外部ServletApi包
 * 2024-07-09 修改了强制仅允许https访问的问题
 * 
 * @author 刘虻
 * 2007-3-6下午01:33:26
 */
@ClassInfo({"2024-07-25 12:40","ServeConnection"})
public class ServeConnection implements Runnable {

	protected long    lastRun;
	protected long    lastWait;
	protected String  decodeReqQuery; // 未进行解码的参数字符串
	protected boolean keepAlive = true;
	
	private Socket               socket; // 通信类
	private Serve                serve;  // 服务类
	private ServletInputStream   in;     // 输入流
	private ServletOutputStream  out;    // 输出流
	private Locale               locale; // = java.util.Locale.getDefault();
	private PrintWriter          pw;
	private ServletOutputStream  rout;
	private String               contextPath;       // 虚拟路径
	private int                  contextPathLength; // 虚拟路径长度
	private BaseFilter           baseFilter;        // 主过滤器
	
	private String   resMessage;
	private String   scheme;            // http https
	private String   reqMethod;
	private String   reqUriPath;
	private String   unCodeReqUriPath;  // 未进行解码的路径字符串
	private String   reqProtocol;
	private String   charEncoding;      // req and resp
	private String   remoteUser;
	private String   authType;
	private String   sessionCookieValue;
	private String   sessionUrlValue;
	private String   sessionValue;
	private String   reqQuery;
	private String[] postCache;
	
	private boolean  oneOne;            // HTTP/1.1 or better
	private boolean  reqMime;
	private boolean  headersWritten;
	
	private Vector<String>        reqHeaderNames = new Vector<String>();
	private Vector<String>        reqHeaderValues = new Vector<String>();
	private Vector<ICookie>       outCookies;
	private Vector<ICookie>       inCookies;
	private Map<String,String[]>  formParameters;
	private FileServe             fileServe = null; // 输出静态资源服务
	private int timesRequested;
	private int resCode = -1;

	private Hashtable<String,Object> attributes     = new Hashtable<String,Object>();
	private Hashtable<String,Object> resHeaderNames = new Hashtable<String,Object>();
	
	private RequestImpl  req;
	private ResponseImpl resp;
	
	private static final SimpleDateFormat expdatefmt       = new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss 'GMT'", Locale.US);
	private static final SimpleDateFormat headerdateformat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
	
	private final String SESSION_URL_NAME = ";$sessionid$";        // jsessionid=
	private final String CONTENTTYPE      = "Content-Type";        // HTML内容类型
	private final String CONNECTION       = "Connection";          // 连接关键字
	private final String HOST             = "Host";                // 主机地址
	private final String CHUNKED          = "chunked";             // HTML头参数
	private final String TRANSFERENCODING = "Transfer-Encoding";   // 传输编码格式
	private final String CONTENTLENGTH    = "Content-Length";      // HTML内容长度
	private final String KEEPALIVE        = "Keep-Alive";          // 是否与浏览器保持连接
	private final String SETCOOKIE        = "Set-Cookie";          // HMTL头信息
	private final String COOKIE           = "Cookie";              // Cookie
	private final String ACCEPT_LANGUAGE  = "Accept-Language";     // HTML Head 信息
	private final String BGCOLOR          = "BGCOLOR=\"#D1E9FE\""; // 默认页面背景颜色
	
	private final String ARG_SERVLET_TRANSFER_ENCODING = "transfer-encoding"; // Servlet传输编码格式
	
	static {
		TimeZone tz = TimeZone.getTimeZone("GMT");
		tz.setID("GMT");
		expdatefmt.setTimeZone(tz);
	}
	
	/**
	 * 构造函数
	 * 2008-7-9上午02:31:02
	 */
	public ServeConnection(Socket socket, Serve serve, BaseFilter baseFilter) {
		this.socket            = socket;
		this.serve             = serve;
		this.fileServe         = new FileServe(serve);
		this.contextPath       = serve.getServeParameter().getContextPath();
		this.contextPathLength = serve.getServeParameter().getContextPathLength();
		this.baseFilter        = baseFilter;
		if (serve.getKeepAliveCleaner() != null) {
			serve.getKeepAliveCleaner().addConnection(this);
		}
		try {
			serve.getThreadManager().executeThread(this);
		}catch(Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取通信类
	 * @author 刘虻
	 * 2008-7-9上午02:31:07
	 * @return 通信类
	 */
	public Socket getSocket() {
		return this.socket;
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:31:25
	 */
    protected void restart() {
        //线程
        Thread cThread = Thread.currentThread();
        cThread.setName("free action ["+cThread.getName()+"]");
		reqMethod = null;
		reqUriPath = null;
		reqProtocol = null;
		charEncoding = null;
		remoteUser = null;
		authType = null;
		oneOne = false;
		reqMime = false;
		if (reqHeaderNames == null) {
            reqHeaderNames = new Vector<String>();
        } else {
            reqHeaderNames.clear();
        }
		if (reqHeaderValues == null) {
            reqHeaderValues = new Vector<String>();
        } else {
            reqHeaderValues.clear();
        }
		locale = null;
		outCookies = null;
		inCookies = null;
		sessionCookieValue = null;
		sessionUrlValue = null;
		sessionValue = null;
		reqQuery = null;
		pw = null;
		rout = null;
		formParameters = null;
		if (attributes == null) {
            attributes = new Hashtable<String, Object>();
        } else {
            attributes.clear();
        }
		resCode = -1;
		resMessage = null;
		resHeaderNames.clear();
		headersWritten = false;
		postCache = null;
		((ServletInputStreamImpl) in).refresh();
		((ServletOutputStreamImpl) out).refresh();
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:31:40
	 */
    @Override
    public void run() {
		try {
			in  = new ServletInputStreamImpl(socket.getInputStream());
			out = new ServletOutputStreamImpl(socket.getOutputStream(), this);
			do {
				restart();
				parseRequest();
				serve.log(socket.getInetAddress().toString()
						+ ':'
						+ socket.getLocalPort()
						+ ' '
						+ reqMethod
						+ ' '
						+ reqUriPath
						+ ' '
						+ resCode
						+ "|"
						+ getHeader("Referer")
						+ "|"
						+ getHeader("User-Agent"));
			
				lastRun = 0;
				timesRequested++;
			} while (keepAlive && serve.isKeepAlive()
					&& timesRequested < serve.getMaxTimesConnectionUse());
		} catch (IOException ioe) {
			// ioe.printStackTrace(); 这种异常没法解决，也不用解决
			serve.log(ioe.getMessage());
		} finally {
			try {
				socket.close();
			} catch (IOException e) { /* ignore */
			}
		}
	}

	
	/**
	 * 解析用户提交请求
	 * @author 刘虻
	 * 2008-2-20下午02:22:20
	 * @throws IOException 之星发生异常
	 */
	@SuppressWarnings("deprecation")
    protected void parseRequest() throws IOException {
		
		req  = new RequestImpl(this,baseFilter);
		resp = new ResponseImpl(this);
		
		byte[] lineBytes = new byte[4096];
		int len;
		String line;
		lastWait = System.currentTimeMillis();
		len = in.readLine(lineBytes, 0, lineBytes.length);
		if (len == -1 || len == 0) {
			if (keepAlive) {
                throw new IOException("Inconsistent input data");
            } else {
				problem("Status-Code 400: Bad Request(empty)",null, IResponse.SC_BAD_REQUEST);
				return;
			}
		}
		if (len >= lineBytes.length) {
			problem("Status-Code 414: Request-URI Too Long",null,
					IResponse.SC_REQUEST_URI_TOO_LONG);
			return;
		}
		line = new String(lineBytes, 0, len);
		StringTokenizer ust = new StringTokenizer(line);
		reqProtocol = null;
		if (ust.hasMoreTokens()) {
			reqMethod = ust.nextToken();
			if (ust.hasMoreTokens()) {
				reqUriPath = ust.nextToken();
				if (reqUriPath!=null) {
					//保留原有编码格式,待setCharacterEncoding可以重新进行编码
					unCodeReqUriPath = reqUriPath;
					if(getCharacterEncoding()!=null) {
						reqUriPath = new String(reqUriPath.getBytes(),getCharacterEncoding());
					}
					Thread.currentThread().setName(reqUriPath);
				}
				int uop = reqUriPath.indexOf(SESSION_URL_NAME);
				if (uop > 0) {
					sessionUrlValue = reqUriPath.substring(uop
							+ SESSION_URL_NAME.length());
					reqUriPath = reqUriPath.substring(0, uop);
					try {
						((SessionImpl)serve.getSession(sessionUrlValue)).userTouch();
					} catch (NullPointerException npe) {
						sessionUrlValue = null;
					} catch (IllegalStateException ise) {
						sessionUrlValue = null;
					}
				}
				if (ust.hasMoreTokens()) {
					reqProtocol = ust.nextToken();
					oneOne = !"HTTP/1.0".equals(reqProtocol.toUpperCase());
					reqMime = true;
					String s;
					String key;
					String value;
					String charset;
					while ((s = ((ServletInputStreamImpl) in).readLine()) != null) {
						if (s.length() == 0) {
                            break;
                        }
						int c = s.indexOf(':');
						if (c > 0) {
							//.toLowerCase()原本key在这里做了强制小写，但这不符合HTTP规范，所以去掉强制小写
							key   = s.substring(0, c).trim();
							value = s.substring(c + 1).trim();
							if(CONTENTTYPE.equalsIgnoreCase(key)) {
								//有的浏览器会提交 application/x-www-form-urlencoded; charset=UTF-8
								//IE浏览器会提交  application/x-www-form-urlencoded
								int point = value.indexOf(";"); //分隔符
								if(point>-1) {

									//提交内容编码
									charset = value.substring(point+1).trim();
									
									//注意：在Tomat中测试  遇到 application/x-www-form-urlencoded; charset=UTF-8 这种情况，并不把后面的charset=UTF-8截取掉
									//      另外在form上传文件时Content-Type需要返回 multipart/form-data; boundary=----WebKitFormBoundaryUskssGJa3IAjlq7I 而不是前半部分
									//value = value.substring(0,point).trim();
									
									point = charset.indexOf("=");
									
									// 除了普通情况的  text/html; charset=UTF-8  还会有文件上传时的 multipart/form-data; boundary=----WebKitFormBoundarymCwxHBA9jw14YRvb
									if(point>-1 && charset.substring(0,point).trim().toUpperCase().equals("CHARSET")) {
										charset = charset.substring(point+1).trim();
										setCharacterEncoding(charset);
									}
								}
							} else if (CONNECTION.equalsIgnoreCase(key)) {
								//因为是轻量级框架，没有设计在输出HTML时获取报文体长度content-length
								//因为如果要获取报文体长度的话，必须缓存所有报文体，然后计算出长度
								//写入报文头，然后输出报文体，这个相对复杂，也耗资源
								//Http1.0 中，如果Connection:keep-alive 则需要在报文头
								//中包含报文体长度，否则做Post后，页面会无响应
								//在做Get时，经过servlet处理后的内容也会混乱
								//所以在Http1.0时，就自动设置为不保持连接
								//目前浏览器都是用的Http1.1，很少会用到Http1.0
								//但也会用到，比如浏览器设置了代理访问时，浏览器设置的高级选项中
								//没有勾选通过代理访问 Http1.1就会出现问题
								if(!oneOne) {
									keepAlive = false;
								}
								//以下是原代码
//								if (oneOne)
//									keepAlive = "close".equalsIgnoreCase(value) == false;
//								else
//									keepAlive = IGlobalVar.KEEPALIVE.equalsIgnoreCase(value);
							}
							reqHeaderNames.addElement(key);
							reqHeaderValues.addElement(value);
						} else {
							serve.log("header field '" + s + "' without ':'");
						}
					}
				} else {
					reqProtocol = "HTTP/0.9";
					oneOne = false;
					reqMime = false;
				}
			}
		}
		if (reqProtocol == null) {
			problem("Malformed request line",null, IResponse.SC_BAD_REQUEST);
			return;
		}
		if (oneOne) {
			String host = getHeader(HOST);
			if (host == null) {
				problem("'Host' header missing on HTTP/1.1 request",null,IResponse.SC_BAD_REQUEST);
				return;
			}
		}
		if (contextPathLength>0 && !reqUriPath.startsWith(contextPath)) {
			problem("URL:["+reqUriPath+"] Not Found",null,IResponse.SC_NOT_FOUND);
			return;
		}
		int qmark = reqUriPath.indexOf('?');
		if (qmark > -1) {
			reqQuery = reqUriPath.substring(qmark + 1);
			if(getCharacterEncoding()==null) {
			    try {
			        reqUriPath = URLDecoder.decode(reqUriPath.substring(0, qmark));
			    }catch(Exception e) {
			        reqUriPath = reqUriPath.substring(0, qmark);
			    }
			}else {
			    try {
			        reqUriPath = URLDecoder.decode(reqUriPath.substring(0, qmark),getCharacterEncoding());
			    }catch(Exception e) {
			        reqUriPath = reqUriPath.substring(0, qmark);
			    }
			}
		} else {
		    try {
		          if(getCharacterEncoding()==null) {
		                reqUriPath = URLDecoder.decode(reqUriPath);
		            }else {
		                reqUriPath = URLDecoder.decode(reqUriPath,getCharacterEncoding());
		            }
		    }catch(Exception e) {}
		}
		if (CHUNKED.equals(getHeader(TRANSFERENCODING))) {
			setHeader(CONTENTLENGTH, null);
			((ServletInputStreamImpl) in).chunking(true);
		}
		//获取内容大小
		String contentLength = getHeader(CONTENTLENGTH);
		if (contentLength != null) {
            try {
                ((ServletInputStreamImpl) in).setContentLength(Long
                        .parseLong(contentLength));
            } catch (NumberFormatException nfe) {
                serve.log("Invalid value of input content-length: "
                        + contentLength);
            }
        }
		if (keepAlive && serve.isKeepAlive()) {
			if (socket.getKeepAlive() == false) {
                socket.setKeepAlive(true);
            }
			if (reqMime) {
				setHeader(CONNECTION, KEEPALIVE);
				if (oneOne) {
                    setHeader(KEEPALIVE, serve.getKeepAliveParamStr());
                }
			}
		} else {
			setHeader(CONNECTION, "close");
		}
		if (reqMime) {
			setHeader("MIME-Version", "1.0");
		}
		
		//检测路径是否为文件夹路径，如果是文件夹路径，则尝试显示默认文件
		reqUriPath = checkUriPath(reqUriPath);
		resp.setStatus(IResponse.SC_OK);
		setDateHeader("Date", System.currentTimeMillis());
		setHeader("Server", Identification.SERVER_NAME + "/" + Identification.SERVER_VERSION);
		try {
			parseCookies(); //解析Cookies
			if (!baseFilter.isTokenMode() && sessionValue == null) {
				sessionValue = sessionUrlValue;
			}
			//通过过滤器链调用Servlet
			if(!serve.filter.doFilter(req,resp)) {
				fileServe.fileServe(req,resp);
			}
			if (pw != null) {
				pw.flush();
			}
			out.close();
		} catch (IOException e) {
			serve.log("IO problem running servlet", e);
			problem("IO problem running servlet: " + e.toString(),e,IResponse.SC_BAD_REQUEST);
		} catch (Exception e) {
			serve.log("Unexpected problem running servlet", e);
			problem("Unexpected problem running servlet: " +e,e,IResponse.SC_INTERNAL_SERVER_ERROR);
		}
		skipPostData();
	}
	
	/**
	 * 检测路径是否为文件夹路径，如果是，则尝试访问默认文件
	 * @author 刘虻
	 * 2010-1-19下午06:00:48
	 * @param uriPath 检测路径
	 * @return 整理后的路径
	 */
	protected String checkUriPath(String uriPath) {
		//检测路径是否为文件夹路径
		String allPath = getRealPath(uriPath);
		if(!allPath.endsWith("/")) {
			allPath += "/";
		}
		File cFile = new File(allPath);
		if(cFile.exists() && cFile.isDirectory()) {
		    File wFile; //默认文件
			for(int i=0;i<serve.getWelcomeFilePages().length;i++) {
				//检测默认文件是否存在
				wFile = new File(allPath+serve.getWelcomeFilePages()[i]);
				if(wFile.exists() && wFile.isFile()) {
					if(uriPath.endsWith("/")) {
						return uriPath+serve.getWelcomeFilePages()[i];
					}
					return uriPath+"/"+serve.getWelcomeFilePages()[i];
				}
			}
		}
		return uriPath;
	}

	/**
	 * 出现问题
	 * @author 刘虻
	 * 2008-7-9上午02:31:57
	 * @param logMessage 母鸡
	 * @param resCode 母鸡
	 */
	protected void problem(String message,Exception e, int resCode) {
		serve.log(message+((e==null)?"":getExceptionInfo(e)));
		try {
			setStatus(resCode, message);
			realSendError(e);
		} catch (IllegalStateException se) { /* ignore */
		} catch (IOException ioe) { /* ignore */
		}
	}
	
    /**
     * 获取异常信息，输出字符串
     * 刘虻
     * 2013-3-19 下午3:05:30
     * @param e 异常对象
     * @param enterStr 换行符
     * @return 异常信息
     */
    protected String getExceptionInfo(Throwable e) {
    	if(e==null) {
    		return "";
    	}
    	//构建返回值
    	StringBuffer reSbf = new StringBuffer("\n");
    	reSbf.append(e).append("\n");
    	//堆栈
    	StackTraceElement[] eles = e.getStackTrace();
    	if(eles!=null) {
    		for(int i=0;i<eles.length;i++) {
    			reSbf.append(eles[i]).append("\n");
    		}
    	}
    	return reSbf.toString();
    }

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:32:07
	 * @param str 母鸡
	 * @return 母鸡
	 */
	public String decode(String str) {
		StringBuffer result = new StringBuffer();
		int l = str.length();
		for (int i = 0; i < l; ++i) {
			char c = str.charAt(i);
			if (c == '%' && i + 2 < l) {
				char c1 = str.charAt(i + 1);
				char c2 = str.charAt(i + 2);
				if (isHexit(c1) && isHexit(c2)) {
					result.append((char) (hexit(c1) * 16 + hexit(c2)));
					i += 2;
				} else {
                    result.append(c);
                }
			} else if (c == '+') {
                result.append(' ');
            } else {
                result.append(c);
            }
		}
		return result.toString();
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:32:15
	 * @param c 母鸡
	 * @return 母鸡
	 */
	protected boolean isHexit(char c) {
		String legalChars = "0123456789abcdefABCDEF";
		return (legalChars.indexOf(c) != -1);
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:32:21
	 * @param c 母鸡
	 * @return 母鸡
	 */
	protected int hexit(char c) {
		if (c >= '0' && c <= '9') {
            return c - '0';
        }
		if (c >= 'a' && c <= 'f') {
            return c - 'a' + 10;
        }
		if (c >= 'A' && c <= 'F') {
            return c - 'A' + 10;
        }
		return 0;
	}

	/**
	 * 解析Cookies
	 * @author 刘虻
	 * 2008-6-28下午07:23:44
	 * @deprecated
	 */
	protected void parseCookies() {
		if (inCookies == null) {
            inCookies = new Vector<ICookie>();
        }
		try {
			String cookie_name;
			String cookie_value;
			String cookie_path;
			String cookies = getHeader(COOKIE);
			if (cookies == null) {
                return;
            }
			StringTokenizer st = new StringTokenizer(cookies, ";", true);
			while (st.hasMoreTokens()) {
				StringTokenizer st2 = new StringTokenizer(st.nextToken(), "=");
				if (st2.hasMoreTokens()) {
					cookie_name = st2.nextToken().trim();
					if (st2.hasMoreTokens()) {
						cookie_value = st2.nextToken(",").trim();
						if (cookie_value.length() > 0
								&& cookie_value.charAt(0) == '=') {
                            cookie_value = cookie_value.substring(1);
                        }
						cookie_path = "/";
						while (st2.hasMoreTokens()) {
							String cookie_atr = st2.nextToken();
							if ("$Version".equalsIgnoreCase(cookie_atr)
									|| "$Path".equalsIgnoreCase(cookie_atr)
									|| "$Domain".equalsIgnoreCase(cookie_atr)) {
								continue;
							}
							cookie_path = cookie_atr;
						}
						ICookie cookie = new CookieImpl(cookie_name, cookie_value);
						cookie.setPath(cookie_path);
						inCookies.addElement(cookie);
						// 如果为token模式，则不再读取会话信息
						if (!baseFilter.isTokenMode() && serve.getSessionCookieName().equals(cookie_name)
								&& sessionCookieValue == null) {
							sessionCookieValue = cookie_value;
							try {
								((SessionImpl)serve.getSession(sessionCookieValue)).userTouch();
								sessionValue = sessionCookieValue;
								sessionUrlValue = null;
							} catch (IllegalStateException ise) {
								sessionCookieValue = null;
							} catch (NullPointerException npe) {
								sessionCookieValue = null;
							}
						}
					}
				}
			}
		} catch (Throwable e) {
			serve.log("prepareCookies(): ", e);
		}
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:32:41
	 */
	public int getContentLength() {
		return getIntHeader(CONTENTLENGTH);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:32:46
	 */
	public String getContentType() {
		return getHeader(CONTENTTYPE);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:32:51
	 */
	public String getProtocol() {
		return reqProtocol;
	}

	
	/**
	 * "http", "https", or "ftp"
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:33:10
	 */
	public String getScheme() {
		if (scheme == null) {
            synchronized (this) {
                if (scheme == null) {
                    scheme = socket.getClass().getName().indexOf("SSLSocket") > 0 ? "https"
                            : "http";
                }
            }
        }
		return scheme;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:33:21
	 */
	public String getServerName() {
		String serverName;
		serverName = getHeader(HOST);
		if (serverName != null && serverName.length() > 0) {
			int colon = serverName.indexOf(':');
			if (colon >= 0) {
				if (colon < serverName.length()) {
                    serverName = serverName.substring(0, colon);
                }
			}
		}

		if (serverName == null) {
			try {
				serverName = InetAddress.getLocalHost().getHostName();
			} catch (java.net.UnknownHostException ignore) {
				serverName = "127.0.0.0";
			}
		}

		int slash = serverName.indexOf("/");
		if (slash >= 0) {
            serverName = serverName.substring(slash + 1);
        }
		return serverName;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:33:29
	 */
	public int getServerPort() {
		return socket.getLocalPort();
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:33:34
	 */
	public String getRemoteAddr() {
		return socket.getInetAddress().getHostAddress();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:34:40
	 */
	public String getRemoteHost() {
		String result = socket.getInetAddress().getHostName();
		return result != null ? result : getRemoteAddr();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:34:50
	 */
	public String getRealPath(String path) {
		return serve.getServletContext().getRealPath(path);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:34:56
	 */
	public InputStream getInputStream() throws IOException {
		synchronized (in) {
			if (((ServletInputStreamImpl) in).isReturnedAsReader()) {
				throw new IllegalStateException("Already returned as a reader.");
			}
			((ServletInputStreamImpl) in).setReturnedAsReader(true);
		}
		return in;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:35:01
	 */
	public BufferedReader getReader() {
		synchronized (in) {
			if (((ServletInputStreamImpl)in).isReturnedAsStream()) {
				throw new IllegalStateException("Already returned as a stream.");
			}
		}
		try {
			return new BufferedReader(new InputStreamReader(in,getServCharEncoding()));
		} catch (UnsupportedEncodingException uee) {}
		return new BufferedReader(new InputStreamReader(in));
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:35:05
	 */
	protected void skipPostData() {
		if (postCache == null && "POST".equals(reqMethod)) {
			if((((ServletInputStreamImpl)in).isReturnedAsReader())) {
				//如果用户在应用程序中使用了getInputStream()读取过了信息，就不用执行这步了
				return;
			}
			InputStream is = null;
			int len = getContentLength();
			try {
				is = getInputStream();
				while (len > 0) {
					long r = is.skip(len);
					if (r > 0) {
                        len -= r;
                    } else {
                        break;
                    }
				}
			} catch (IOException ex) {
				serve.log("IOException " + ex
						+ " at skipping 'POST' data of length " + len);
			} finally {
				if (is != null) {
                    try {
                        is.close();
                    } catch (IOException ioe) {
                    }
                }
			}
		}
	}
	
	/**
	 * 获取系统编码
	 * @author 刘虻
	 * 2010-1-20下午02:36:29
	 * @return 系统编码
	 */
	protected String getServCharEncoding() {
		if(charEncoding==null) {
			charEncoding = 
				serve.getServeParameter()
					.getArgumentString(ARG_SERVLET_TRANSFER_ENCODING);
			if(charEncoding==null || charEncoding.length()<1) {
				charEncoding = "UTF-8"; //使用固定的UTF-8编码
			}
		}
		return charEncoding;
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:35:22
	 * @return
	 */
	protected synchronized Map<String,String[]> getParametersFromRequest() {
		//构造返回值
		Map<String,String[]> result = new Hashtable<String,String[]>();
		if ("GET".equals(reqMethod)) {
			if (reqQuery != null) {
                try {
                    parseQueryString(result,reqQuery,getServCharEncoding());
                } catch (IllegalArgumentException ex) {
                    serve.log("Exception " + ex + " at parsing 'get' data "
                            + reqQuery);
                }
            }
		} else if ("POST".equals(reqMethod)) {
			if (reqQuery != null && reqQuery.length() > 0) {
				try {
					parseQueryString(result,reqQuery,getServCharEncoding());
				}catch(Exception e) {}
			}
			if (postCache == null) {
				postCache = new String[1];
				InputStream is = null;
				try {
					parsePostData(result,getContentLength(),
							is = getInputStream(), getServCharEncoding(), postCache);
				} catch (Exception ex) {
					serve.log("Exception " + ex
							+ " at parsing 'POST' data of length "
							+ getContentLength());
				} finally {
					if (is != null) {
                        try {
                            is.close();
                        } catch (IOException ioe) {
                        }
                    }
				}
			} else {
				parseQueryString(result,postCache[0],getServCharEncoding());
			}
		}
		return result;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:35:35
	 */
	public synchronized Enumeration<String> getParameterNames() {
		if (formParameters == null) {
			formParameters = getParametersFromRequest();
		}
		return ((Hashtable<String,?>) formParameters).keys();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:35:47
	 */
	public String getParameter(String name) {
		String[] params = getParameterValues(name);
		if (params == null || params.length == 0) {
            return null;
        }

		return params[0];
	}

	/**
	 * 设置参数值
	 * @param name    参数名
	 * @param value   参数值
	 * 2022年8月30日
	 * @author MBG
	 */
	public void setParameter(String name,String value) {
		String[] params = new String[] {value};
		if (formParameters == null) {
            getParameterNames();
        }
		formParameters.put(name,params);
	}
	
	/**
	 * 设置参数值
	 * @param name    参数名
	 * @param value   参数值
	 * 2022年8月30日
	 * @author MBG
	 */
	public void setParameter(String name,String[] values) {
		if (formParameters == null) {
            getParameterNames();
        }
		formParameters.put(name,values);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:35:57
	 */
	public synchronized String[] getParameterValues(String name) {
		if (formParameters == null) {
            getParameterNames();
        }

		return formParameters.get(name);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:36:04
	 */
	public Object getAttribute(String name) {
		return attributes.get(name);
	}
	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:36:09
	 */
	public ICookie[] getCookies() {
		ICookie[] cookieArray = new CookieImpl[inCookies.size()];
		inCookies.copyInto(cookieArray);
		return cookieArray;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:36:15
	 */
	public String getMethod() {
		return reqMethod;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:36:24
	 */
	public String getRequestURI() {
		return reqUriPath;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:36:31
	 */
	public StringBuffer getRequestURL() {
		//获取主机地址
		String host = getHeader("Host");
		String scheme = getScheme(); //协议名
		if(host==null || host.length()<1) {
			int port = getServerPort();
			if(!("http".equals(scheme) && port==80) || ("https".equals(scheme) && port==443) ) {
				host = getLocalAddr()+":"+port;
			}
		}
		//因为Tomcat 和 WebLogic 都不返回带参数的URL，所以这里也取消参数字符串
//		return new StringBuffer().append(getScheme()).append("://").append(host).append(getRequestURI())
//				.append((reqQuery==null || reqQuery.length()<1)?"":"?"+reqQuery);
		return new StringBuffer().append(getScheme()).append("://").append(host).append(getRequestURI());
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:36:44
	 */
	public String getServletPath() {
		//构建返回值
		String rePath = reqUriPath;
		if (rePath.startsWith(contextPath)) {
			return rePath.substring(contextPathLength);
		}
		return rePath;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:36:53
	 */
	public String getPathInfo() {
		return reqUriPath;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:06
	 */
	public String getPathTranslated() {
		return getRealPath(getPathInfo());
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:12
	 */
	public String getQueryString() {
		return reqQuery;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:18
	 */
	public String getRemoteUser() {
		return remoteUser;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:25
	 */
	public String getAuthType() {
		return authType;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:30
	 */
	public String getHeader(String name) {
		int i = reqHeaderNames.indexOf(name);
		if (i == -1) {
            return null;
        }
		return reqHeaderValues.elementAt(i);
	}
	
	/**
	 * 从反馈对象中获取即将返回的头信息
	 * @param name 头名
	 * @return     值
	 * 2024年7月25日
	 * @author MBG
	 */
	public Object getResponseHeader(String name) {
		return resHeaderNames.get(name);
	}
	
	/**
	 * 获取指定名称的报文头值数组
	 * @param name 报文头名
	 * @return     值数组
	 * 2022年8月30日
	 * @author MBG
	 */
	public String[] getHeadersArray(String name) {
		if(name==null) {
			return null;
		}
		//构建返回值序列
		List<String> rList = new ArrayList<>();
		String key;
		for(int i=0;i<reqHeaderNames.size();i++) {
			key = reqHeaderNames.get(i);
			if(name.equals(key)) {
				rList.add(reqHeaderValues.get(i));
			}
		}
		//构建返回值
		String[] res = new String[rList.size()];
		rList.toArray(res);
		return res;
	}
	
	/**
	 * 返回报文头名序列
	 * @return 报文头名序列
	 * 2022年8月30日
	 * @author MBG
	 */
	public Collection<String> getHeaderNames(){
		return reqHeaderNames;
	}
	
	/**
	 * 获取头信息容器
	 * @return 头信息容器
	 * 2022年8月30日
	 * @author MBG
	 */
	public Map<String,String> getHeaderMap(){
		Map<String,String> reMap = new HashMap<>();
		for(int i=0;i<reqHeaderNames.size();i++) {
			reMap.put(reqHeaderNames.get(i),reqHeaderValues.get(i));
		}
		return reMap;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:34
	 */
	public int getIntHeader(String name) {
		String val = getHeader(name);
		if (val == null) {
            return -1;
        }
		return Integer.parseInt(val);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:37
	 */
	public long getDateHeader(String name) {
		String val = getHeader(name);
		if (val == null) {
            return -1;
        }
		try {
			return headerdateformat.parse(val).getTime();
		} catch (Exception e) {
			throw new IllegalArgumentException("Value " + val
					+ " can't be converted to Date using "
					+ headerdateformat.toPattern());
		}
	}




	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:51
	 * @deprecated
	 */
	public synchronized IHttpSession getSession(boolean create) {
		if(baseFilter.isTokenMode()) {
			return new SessionImpl(
					null,serve.getServletContext()
					,serve.getSessionContextImpl(),this,baseFilter);
		}
		IHttpSession result = null;
		if (sessionValue != null) {
			result = serve.getSession(sessionValue);
			if (result == null || ((SessionImpl)result).checkExpired()) {
				serve.removeSession(sessionValue);
				result = null;
			}
		}
		if (result == null && create) {
			result = serve.createSession(this,baseFilter);
			if (result != null) {
				sessionValue = result.getId();
			}
		}
		return result;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:57
	 */
	public IHttpSession getSession() {
		return getSession(true);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:37:59
	 */
	public boolean isRequestedSessionIdFromURL() {
		return false;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:05
	 */
	public Enumeration<String> getAttributeNames() {
		return attributes.keys();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:08
	 */
	public void setAttribute(String key, Object o) {
		// System.err.println("!!!Set att orig:"+key+"="+o);
		if (o != null) {
            attributes.put(key, o);
        } else {
            attributes.remove(key);
        }
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:14
	 */
	public String getRequestedSessionId() {
		return sessionValue;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:18
	 * @deprecated
	 */
	public boolean isRequestedSessionIdValid() {
		if (sessionValue != null) {
			IHttpSession session = serve.getSession(sessionValue);
			return (session != null && ((SessionImpl)session).isValid());
		}
		return false;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:23
	 */
	public boolean isRequestedSessionIdFromCookie() {
		return sessionCookieValue != null;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:31
	 */
	public boolean isRequestedSessionIdFromUrl() {
		return sessionUrlValue != null;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:35
	 */
	public void setContentLength(int length) {
		setIntHeader(CONTENTLENGTH, length);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:43
	 */
	public void setContentType(String type) {
		setHeader(CONTENTTYPE, type != null ? type : "Unknown");
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:48
	 */
	public ServletOutputStream getOutputStream() {
		synchronized (out) {
			if (rout == null) {
				if (pw != null) {
                    throw new IllegalStateException(
                            "Already returned as a writer");
                }
				rout = out;
			}
		}
		return rout;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:54
	 */
	public PrintWriter getWriter() throws IOException {
		synchronized (out) {
			if (pw == null) {
				if (rout != null) {
                    throw new IllegalStateException(
                            "Already was returned as servlet output stream");
                }
				String encoding = getCharacterEncoding();
				if (encoding != null) {
                    pw = new PrintWriter(new OutputStreamWriter(out, encoding));
                } else {
                    pw = new PrintWriter(out);
                }
			}
		}
		return pw;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:38:59
	 */
	public String getCharacterEncoding() {
		Object value = resHeaderNames.get(CONTENTTYPE);
		String ct = null;
		if(value!=null) {
		    if(value instanceof String[]) {
		        if(((String[])value).length>0) {
		            ct = ((String[])value)[0];
		        }else {
		            ct = (String)value;
		        }
		    }else {
		    	ct = value.toString();
		    }
		}
		if (ct != null) {
			int scp = ct.indexOf(';');
			if (scp > 0) {
				scp = ct.toLowerCase().indexOf("charset=", scp);
				if (scp >= 0) {
					ct = ct.substring(scp + 8);
					scp = ct.indexOf(' ');
					if (scp > 0) {
                        ct = ct.substring(0, scp);
                    }
					scp = ct.indexOf(';');
					if (scp > 0) {
                        ct = ct.substring(0, scp);
                    }
					int l = ct.length();
					if (ct.charAt(0) == '"' && l > 2) {
						return ct.substring(1, l - 1);
					}
					return ct;
				}
			}
		}
		//获取不到时就为空 参考于Tomcat 5.3.0
//		if (charEncoding==null || charEncoding.length()<1) {
//			charEncoding =
//				serve
//					.getServeParameter()
//						.getArgumentString(IGlobalVar.ARG_SERVLET_TRANSFER_ENCODING);
//			if(charEncoding==null || charEncoding.length()<1) {
//				charEncoding = IGlobalVar.ISO88591;
//			}
//		}
		return charEncoding;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:08
	 */
	public void flushBuffer() {}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:13
	 */
	public void resetBuffer() {
		throw new IllegalStateException("The method not implemented");
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:16
	 */
	public int getBufferSize() {
		return 0;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:19
	 */
	public void setBufferSize(int size) {}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:27
	 */
	public boolean isCommitted() {
		return headersWritten;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:32
	 */
	public void reset() throws IllegalStateException {
		if (!isCommitted()) {
			if (outCookies != null) {
                outCookies.clear();
            }
			resHeaderNames.clear();
		} else {
            throw new IllegalStateException(
                    "Header have already been committed.");
        }
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:38
	 */
	public void setLocale(java.util.Locale locale) {
		this.locale = locale;
	}

	
	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:50
	 */
	public java.util.Locale getLocale() {
		if (locale != null) {
            return locale;
        }
		Enumeration<Locale> e = getLocales();
		if (e.hasMoreElements()) {
            return e.nextElement();
        }
		return Locale.getDefault();
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:39:53
	 */
	@SuppressWarnings("unchecked")
    public Enumeration<Locale> getLocales() {
		String al = getHeader(ACCEPT_LANGUAGE);
		TreeSet<LocaleWithWeight> ts = new TreeSet<LocaleWithWeight>();
		if (al != null) {
			StringTokenizer st = new StringTokenizer(al, ";", false);
			try {
				while (st.hasMoreTokens()) {
					String langs = st.nextToken(";");
					String q = st.nextToken(";=");
					q = st.nextToken("=,");
					float w = 0;
					try {
						w = Float.valueOf(q).floatValue();
					} catch (NumberFormatException nfe) {
					}
					if (w > 0) {
						StringTokenizer lst = new StringTokenizer(langs, ", ",
								false);
						while (lst.hasMoreTokens()) {
							String lan = lst.nextToken();
							int di = lan.indexOf('-');
							if (di < 0) {
                                ts.add(new LocaleWithWeight(new Locale(lan
                                        .trim()), w));
                            } else {
                                ts.add(new LocaleWithWeight(
                                        new Locale(lan.substring(0, di), lan
                                                .substring(di + 1).trim()
                                                .toUpperCase()), w));
                            }
						}
					}
				}
			} catch (NoSuchElementException ncee) {}
		}
		if (ts.size() == 0) {
            ts.add(new LocaleWithWeight(Locale.getDefault(), 1));
        }
		return new AcceptLocaleEnumeration(ts);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:00
	 */
	public void setCharacterEncoding(String _enc) {
		charEncoding = _enc;
		synchronized (this) {
			if (unCodeReqUriPath!=null && _enc!=null) {
				//重新进行解码
				reqUriPath = unCodeReqUriPath;
				try {
					reqUriPath = new String(reqUriPath.getBytes(),_enc);
					int qmark = reqUriPath.indexOf('?');
					if (qmark > -1) {
						reqQuery = reqUriPath.substring(qmark + 1);
						reqUriPath = URLDecoder.decode(reqUriPath.substring(0, qmark),_enc);
					} else {
						reqUriPath = URLDecoder.decode(reqUriPath,_enc);
					}
				}catch(Exception e) {}
			}
			formParameters = null;
		}
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:03
	 */
	public void addDateHeader(String header, long date) {
		addHeader(header, expdatefmt.format(new Date(date)));
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:06
	 */
	public void addHeader(String header, String value) {
		header = header.trim();
		Object o = resHeaderNames.get(header);
		if (o == null) {
            setHeader(header, value);
        } else {
			if (o instanceof String[]) {
				String[] oldVal = (String[]) o;
				String[] newVal = new String[oldVal.length + 1];
				System.arraycopy(oldVal, 0, newVal, 0, oldVal.length);
				newVal[oldVal.length] = value;
				resHeaderNames.put(header, newVal);
			} else if (o instanceof String) {
				String[] newVal = new String[2];
				newVal[0] = (String) o;
				newVal[1] = value;
				resHeaderNames.put(header, newVal);
			} else {
                throw new RuntimeException("Invalid content of header hash - "
                        + o.getClass().getName());
            }
		}
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:11
	 */
	public void addIntHeader(String header, int value) {
		addHeader(header, Integer.toString(value));
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:13
	 */
	public IRequestDispatcher getRequestDispatcher(String urlpath) {
		return null;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:22
	 */
	public boolean isSecure() {
		return "https".equals(getScheme());
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:24
	 */
	public void removeAttribute(String name) {
		attributes.remove(name);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:30
	 */
	public String getContextPath() {
		return contextPath;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:34
	 */
	/*
	public Enumeration<String> getHeaders(String header) {
		Vector result = new Vector();
		int i = -1;
		while ((i = reqHeaderNames.indexOf(header, i + 1)) >= 0)
			result.addElement(reqHeaderValues.elementAt(i));
		return result.elements();
	}
	*/

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:37
	 */
	public java.security.Principal getUserPrincipal() {
		return null;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:41
	 */
	public boolean isUserInRole(String user) {
		return false;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:47
	 */
	public synchronized java.util.Map<String,String[]> getParameterMap() {
		if (formParameters == null) {
            getParameterNames();
        }
		return formParameters;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:40:51
	 */
	public void addCookie(ICookie cookie) {
		if (outCookies == null) {
            outCookies = new Vector<ICookie>();
        }

		outCookies.addElement(cookie);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:41:00
	 */
	public boolean containsHeader(String name) {
		return resHeaderNames.contains(name);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:41:06
	 */
	public String encodeURL(String url) {
		int uop = url.indexOf(SESSION_URL_NAME);
		if (uop > 0) {
            url = url.substring(0, uop);
        }
		if (sessionValue == null || isRequestedSessionIdFromCookie()) {
            return url;
        }
		int ehp = url.indexOf('/');
		if (ehp < 0) {
            ehp = url.indexOf('?');
        }
		if (ehp < 0) {
            ehp = url.indexOf('#');
        }
		if (ehp < 0) {
            ehp = url.length();
        }
		if (url.regionMatches(true, 0, getRequestURL().toString(), 0, ehp) == false) {
            return url;
        }
		return url + SESSION_URL_NAME + sessionValue;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:41:11
	 */
	public String encodeRedirectURL(String url) {
		return encodeURL(url);
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:41:15
	 */
	public int getRemotePort() {
		return getServerPort();
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:41:20
	 */
	public String getLocalName() {
		InetAddress ia = socket/* serve.serverSocket */.getInetAddress();
		return ia == null ? null : ia.getHostAddress();
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:41:25
	 */
	public String getLocalAddr() {
		InetAddress ia = /* serve.serverSocket */socket.getInetAddress();
		return ia == null ? null : ia.getCanonicalHostName();
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:41:30
	 */
	public int getLocalPort() {
		return getServerPort();
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:42:16
	 */
	public void setStatus(int resCode, String resMessage) {
		this.resCode = resCode;
		this.resMessage = resMessage;
	}


	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:42:39
	 */
	public void setHeader(String header, String value) {
		header = header.trim();
		if (value == null) {
            resHeaderNames.remove(header);
        } else {
			resHeaderNames.put(header, value);
		}
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:42:44
	 */
	public void setIntHeader(String header, int value) {
		setHeader(header, Integer.toString(value));
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:42:48
	 * @param header 母鸡
	 * @param value 母鸡
	 */
	public void setLongHeader(String header, long value) {
		setHeader(header, Long.toString(value));
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:43:00
	 */
	public void setDateHeader(String header, long value) {
		try {
			setHeader(header, expdatefmt.format(value<1?new Date():new Date(value)));
		}catch(Exception e) {}
	}

	/**
	 * 母鸡
	 * @author 刘虻
	 * 2008-7-9上午02:43:04
	 * @throws IOException 执行发生异常
	 */
	public void writeHeaders() throws IOException {
		synchronized (this) {
			if (headersWritten) {
				return;
			}
			headersWritten = true;
		}
		if (reqMime) {
			boolean chunked_out = false;
			boolean wasContentLen = false;
			if(resMessage==null){
				out.println(reqProtocol + " " + resCode);
			}else {
				if (resMessage.length() < 256) {
					out.println(reqProtocol + " " + resCode + " "
							+ resMessage.replace('\r', '/').replace('\n', '/'));
				}else {
					out.println(reqProtocol
							+ " "
							+ resCode
							+ " "
							+ resMessage.substring(0, 255).replace('\r', '/')
							.replace('\n', '/'));
				}
			}
			Enumeration<String> he = resHeaderNames.keys();
			while (he.hasMoreElements()) {
				String name = he.nextElement();
				Object o = resHeaderNames.get(name);
				if (o instanceof String) {
					String value = (String) o;
					if (value != null) {
						out.println(name + ": " + value);
						if (wasContentLen == false) {
							if (CONTENTLENGTH.equals(name)) {
								try {
									wasContentLen = Long.parseLong(value) > 0;
								} catch (NumberFormatException nfe) {
								}
							}
						}
						if (chunked_out == false) {
							if (TRANSFERENCODING.equals(name)
									&& CHUNKED.equals(value)) {
								chunked_out = true;
							}
						}
					}
				} else if (o instanceof String[]) {
					String[] values = (String[]) o;
					out.println(name + ": " + values[0]);
					for (int i = 0; i < values.length; i++) {
						out.print("," + values[i]);
					}
					out.println();
				}
			}
			StringBuffer sb = null;
			ICookie cc = null;
			// 如果是token模式，就不在浏览器中放入会话主键值了
			if (!baseFilter.isTokenMode() && sessionValue != null) {
				cc = new CookieImpl(serve.getSessionCookieName(), sessionValue);
				//设置会话安全
				cc.setSecure(serve.getServeParameter().isSecure());
				cc.setHttpOnly(serve.getServeParameter().isHttpOnly());
				if (serve.getServeParameter().getSessionTimeOut() < 0) {
					cc.setMaxAge(Math.abs(serve.getServeParameter().getSessionTimeOut()) * 60);
				}
				addCookie(cc);
			}
			for (int i = 0; outCookies != null && i < outCookies.size(); i++) {
				if (sb == null) {
					sb = new StringBuffer(SETCOOKIE + ": ");
				}else {
					sb.append("\r\n" + SETCOOKIE + ": ");
				}
				cc = outCookies.elementAt(i);
				sb.append(cc.getName());
				sb.append('=');
				sb.append(cc.getValue());
				if (cc.getComment() != null) {
					sb.append("; Comment=" + cc.getComment());
				}
				if (cc.getDomain() != null) {
					sb.append("; domain=" + cc.getDomain());
				}
				if (cc.getMaxAge() >= 0 && !cc.isHttpOnly()) {
					sb.append("; expires=");
					sb.append(expdatefmt.format(new Date(System
							.currentTimeMillis()
							+ 1000 * cc.getMaxAge())));
				}
				if (cc.getPath() == null) {
					sb.append("; Path=/");
				}else {
					sb.append("; Path=" + cc.getPath());
				}
				if (cc.getSecure()) {
					sb.append("; Secure");
				}
				if(cc.isHttpOnly()){
					sb.append("; HttpOnly");
				}
				if (cc.getVersion() > 0 && !cc.isHttpOnly()) {
					sb.append("; Version=" + cc.getVersion());
				}
			}
			if (sb != null) {
				out.println(sb.toString());
			}
			if (wasContentLen == false && chunked_out == false
					&& serve.isKeepAlive() && keepAlive) {
				out.println(TRANSFERENCODING + ": " + CHUNKED);
				chunked_out = true;
			}
			out.println("");
			out.flush();
			((ServletOutputStreamImpl) out).setChunked(chunked_out);
		}
	}

	/**
	 * 发送错误信息到页面
	 * @author 刘虻
	 * 2008-7-9上午02:43:45
	 * @param e 异常
	 * @throws IOException 执行发生异常
	 */
	protected void realSendError(Exception e) throws IOException {
		if (isCommitted()) {
            throw new IllegalStateException(
                    "Can not send error, headers have been already written");
        }
		setContentType("text/html");
		StringBuffer sb = new StringBuffer(100);
		int lsp = resMessage.indexOf('\n');
		sb.append("<HTML><HEAD>").append(
				"<TITLE>" + resCode + " "
						+ (lsp < 0 ? resMessage : resMessage.substring(0, lsp))
						+ "</TITLE>").append(
				"</HEAD><BODY " + BGCOLOR).append(
				"><H2>" + resCode + " "
						+ (lsp < 0 ? resMessage : resMessage.substring(0, lsp))
						+ "</H2>");
		if (lsp > 0 || e!=null) {
            sb.append("<PRE>").append(
                    StringUtil.htmlEncode(((lsp>0)?resMessage.substring(lsp):"")+getExceptionInfo(e), false)).append(
                    "</PRE>");
        }
		sb.append("<HR>");
		Identification.writeAddress(sb);
		sb.append("</BODY></HTML>");
		setContentLength(sb.length());
		out.print(sb.toString());
		out.flush();
		out.close();
	}

	
	/**
	 * 解析提交参数
	 * @author 刘虻
	 * 2008-7-1下午01:10:36
	 * @param result 参数容器
	 * @param query 提交参数字符串
	 * @param encoding 参数编码
	 * @return 参数容器
	 */
	protected void parseQueryString(Map<String,String[]> result,String query,String encoding) {
		StringTokenizer st = new StringTokenizer(query, "&");
		while (st.hasMoreTokens()) {
			String pair = st.nextToken();
			int ep = pair.indexOf('=');
			String key = ep > 0 ? pair.substring(0, ep) : pair;
			String value = ep > 0 ? pair.substring(ep + 1) : null;
			try {
				key = /* URLDecoder. */StringUtil.decode(key,encoding);
				if (value != null) {
					value = /* URLDecoder. */StringUtil.decode(value,encoding);
				}
			} catch (UnsupportedEncodingException uee) {}
			String[] values = result.get(key);
			String[] newValues;
			if (values == null) {
				newValues = new String[1];
				newValues[0] = value;
			} else {
				newValues = new String[values.length + 1];
				System.arraycopy(values, 0, newValues, 0, values.length);
				newValues[values.length] = value;
			}
			result.put(key, newValues);
		}
	}

	/**
	 * 解析提交参数
	 * @author 刘虻
	 * 2008-7-9上午07:42:55
	 * @param res 参数容器
	 * @param len  参数信息长度
	 * @param is 参数信息流
	 * @param encoding 参数编码
	 * @param cachedStream 缓存
	 * @throws IOException 执行发生异常
	 */
	protected void parsePostData(Map<String,String[]> res,long len, InputStream is, String encoding, String[] cachedStream)
			throws IOException {
		byte[] buf = new byte[(int) len];
		int fp = 0;
		while (fp < len) {
			int c = is.read(buf, fp, buf.length - fp);
			if (c < 0) {
                break;
            }
			fp += c;
		}
		if (cachedStream != null && cachedStream.length > 0) {
			parseQueryString(res,cachedStream[0] = new String(buf, 0, fp, encoding), encoding);
		}else {
			parseQueryString(res,new String(buf, 0, fp, encoding), encoding);
		}
	}
	
	/**
	 * 重定向
	 * @param location     目标位置
	 * @throws IOException 异常
	 * 2022年8月31日
	 * @author MBG
	 */
    public void sendRedirect(String location) throws IOException {
        if (isCommitted()) {
            //已经发送完头信息,不能再次发送头信息(包含重定向)
            throw new IllegalStateException(
              "Can not redirect, headers have been already written");
        }
        //全路径
        if (location.indexOf(":/") < 0) {
            StringBuffer portString = new StringBuffer(); //构建提交字符串
            if ("https".equalsIgnoreCase(getScheme())) {
                if (getServerPort()!= 43) {
                    portString.append(":").append(getServerPort());
                }
            } else if (getServerPort() != 80) {
                portString.append(":").append(getServerPort());
            }
            if (location.length() > 0 && location.charAt(0) == '/') {
                location = getScheme()+"://"+getServerName()+portString+location;
                
            } else {
                int sp = reqUriPath.lastIndexOf('/');
                String uri;
                if (sp < 0) {
                    uri = reqUriPath + '/';
                    sp = uri.length();
                } else {
                    uri = reqUriPath;
                    sp++;
                }
                location = getScheme() + "://" + getServerName() + portString
                  + uri.substring(0, sp) + location;
            }
        }
        serve.log("Location:"+location);
        setHeader("Location", location);
        setStatus(IResponse.SC_MOVED_TEMPORARILY,null);
        setContentType("text/html");
        StringBuffer sb = new StringBuffer(200);
        sb
            .append("<HTML><HEAD><TITLE>")
            .append(IResponse.SC_MOVED_TEMPORARILY)
            .append(" Moved</TITLE></HEAD><BODY ")
            .append(BGCOLOR)
            .append("><H2>")
            .append(IResponse.SC_MOVED_TEMPORARILY)
            .append(" Moved</H2>")
            .append("This document has moved <a href=")
            .append(location)
            .append(">here.<HR>");
        Identification.writeAddress(sb);
        sb.append("</BODY></HTML>");
        setContentLength(sb.length());
        out.print(sb.toString());
        out.flush();
        out.close();
    }
    
    /**
     * 获取指定报文头的值序列
     * @param arg0 报文头名
     * @return     值序列
     * 2022年8月31日
     * @author MBG
     */
    public Collection<String> getHeaders(String arg0) {
    	return reqHeaderValues;
    }
    
    /**
     * 获取状态码
     * @return 状态码
     * 2022年8月31日
     * @author MBG
     */
    public int getStatus() {
        return resCode;
    }
	
	/**
	 * 是否使用了内置服务
	 * @return 是否使用了内置服务
	 * 2022年8月30日
	 * @author MBG
	 */
    public boolean isNativeServ() {
        if (serve != null) {
        	return serve.isNativeServ;
        }
        return false;
    }

	/**
	 * 是否长链接
	 * @return 是否长链接
	 * 2022年8月30日
	 * @author MBG
	 */
	public boolean isKeepAlive() {
		return this.keepAlive;
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:44:05
	 */
	public String encodeUrl(String url) {
		return encodeURL(url);
	}

	/**
	 * 覆盖方法
	 * @author 刘虻
	 * 2008-7-9上午02:44:12
	 */
	public String encodeRedirectUrl(String url) {
		return encodeRedirectURL(url);
	}
}